home *** CD-ROM | disk | FTP | other *** search
- /* TrackEdit.c */
- /*
- * Copyright © 1989 Martin Minow. All rights reserved.
- *
- * TrackCut(track_handle)
- * track_handle The TrackRecord handle
- *
- * Cut the selection to the Track private scrap.
- * Anything currently in the scrap is deleted. If there
- * is no selection, the scrap is emptied.
- *
- * TrackCopy(track_handle)
- * track_handle The TrackRecord handle
- *
- * Copy the selection to the Track private scrap.
- * Anything currently in the scrap is deleted. If there
- * is no selection, the scrap is emptied.
- *
- * TrackPaste(track_handle)
- * track_handle The TrackRecord handle
- *
- * Replace the selection range with the contents of the
- * Track private scrap. If the scrap is empty, the
- * selection range is deleted. The private scrap is
- * not changed.
- *
- * TrackDelete(track_handle)
- * track_handle The TrackRecord handle
- *
- * Delete the selection range, but do not copy it to
- * the Track private scrap.
- */
-
- #include "TrackEdit.h"
- #define TR (*tr)
- #define LEFT FALSE
- #define RIGHT TRUE
- #define NIL 0L
- #define NOT_NIL 1L
-
- static void do_paste(TrackHandle);
- static void do_clear(TrackHandle, Boolean);
- static Boolean is_at_space(TrackPtr, Boolean);
- static Boolean is_at_word(TrackPtr, DOT, DOT, Boolean);
-
- /*
- * TrackCut(track_handle)
- * Copy the selection to the scrap, then remove it.
- */
- void
- TrackCut(track_handle)
- TrackHandle track_handle;
- {
- TrackCopy(track_handle);
- TrackDelete(track_handle);
- }
-
- /*
- * TrackCopy(track_handle)
- * Copy the selection to the scrap.
- * This is the only routine to change TrackScrpHandle.
- */
- void
- TrackCopy(track_handle)
- TrackHandle track_handle;
- {
- register TrackPtr tr;
- _Track_state state;
- register long size;
-
- tr = _Track_lock(track_handle, &state);
- size = TR.selEnd - TR.selStart;
- SetHandleSize(TrackScrpHandle, size);
- if (MemErr == noErr) {
- BlockMove(
- &(*TR.hText)[TR.selStart],
- *TrackScrpHandle,
- size
- );
- TrackScrpLength = size;
- }
- _Track_unlock(&state);
- }
-
- /*
- * TrackPaste(track_handle)
- * Replace the selection with the scrap
- */
- void
- TrackPaste(track_handle)
- TrackHandle track_handle;
- {
- _Track_state state;
-
- _Track_lock(track_handle, &state);
- _Track_do_paste(track_handle);
- _Track_unlock(&state);
- }
-
- /*
- * TrackDelete(track_handle)
- * Remove the selection.
- */
- void
- TrackDelete(track_handle)
- TrackHandle track_handle;
- {
- _Track_state state;
-
- _Track_lock(track_handle, &state);
- _Track_do_clear(track_handle, TRUE, TRUE);
- _Track_unlock(&state);
- }
-
- /*
- * _Track_do_paste(track_handle)
- * If a selection exists, remove it; then insert the
- * current scrap. Select the newly-inserted data.
- * Use "intelligent paste" if available. Note that
- * _Track_do_paste() may unlock the TrackRecord
- * temporarily.
- */
- void
- _Track_do_paste(track_handle)
- TrackHandle track_handle;
- {
- register TrackPtr tr;
- _Track_state state;
- DOT start;
-
- tr = *track_handle;
- _Track_caret(tr, _Track_caret_off);
- _Track_do_clear(track_handle, FALSE, TRUE);
- tr = *track_handle;
- start = TR.selStart;
- /*
- * This is needed only for "intelligent paste."
- * Insert a space before the selection if there
- * is a word before the selection.
- */
- if (is_at_word(tr, 0, TR.selStart, RIGHT)) {
- _Track_do_insert(tr, TR.selStart, " ", 1L);
- TR.selStart++;
- }
- HLock(TrackScrpHandle);
- _Track_do_insert(
- tr, TR.selStart, *TrackScrpHandle, TrackScrpLength);
- HUnlock(TrackScrpHandle);
- TR.selEnd = TR.selStart + TrackScrpLength;
- /*
- * This is needed only for "intelligent paste."
- * Insert a space after the selection if there
- * is a word after the selection.
- */
- if (is_at_word(tr, TR.selEnd, TR.textLength, LEFT))
- _Track_do_insert(tr, TR.selEnd, " ", 1L);
- _Track_rebuild(track_handle, start);
- }
-
- /*
- * _Track_do_insert(track_ptr, offset, src, size)
- * Stuff something into the text.
- */
- void
- _Track_do_insert(tr, offset, src, size)
- TrackPtr tr;
- long offset;
- Ptr src;
- long size;
- {
- Munger(TR.hText, offset, NIL, 0L, src, size);
- if (MemErr == noErr)
- TR.textLength = GetHandleSize(TR.hText);
- }
-
- /*
- * _Track_do_clear(track_handle, rebuild, smart)
- * If a selection exists, delete it; then rebuild the
- * lineStarts vector if requested. Use "intelligent cut"
- * if available and smart is TRUE. _Track_do_clear() may
- * temporarily unlock the TrackRecord.
- */
- void
- _Track_do_clear(track_handle, rebuild, smart)
- TrackHandle track_handle;
- Boolean rebuild;
- Boolean smart;
- {
- register TrackPtr tr;
- long size;
-
- tr = (*track_handle);
- if (TR.selEnd != TR.selStart) {
- /*
- * There is a selection. If the character to the
- * left or right of the current selection is a
- * space, cut it along with the selection.
- * is_at_space() fails if "intelligent cut and
- * paste" is disabled.
- */
- if (smart) {
- if (is_at_space(tr, LEFT))
- --TR.selStart;
- else if (is_at_space(tr, RIGHT))
- ++TR.selEnd;
- }
- size = TR.selEnd - TR.selStart;
- Munger(TR.hText, TR.selStart, NIL, size, NOT_NIL, 0);
- TR.textLength -= size;
- SetHandleSize(TR.hText, TR.textLength);
- TR.selEnd = TR.selStart;
- if (rebuild)
- _Track_rebuild(track_handle, TR.selStart);
- }
- }
-
- /*
- * is_at_space(direction)
- * Use the ScriptMgr FindWord procedure to determine if
- * the designated end of the selection is a word with an
- * adjacent space. It is needed only for "intelligent
- * cut and paste."
- */
- static Boolean
- is_at_space(tr, direction)
- register TrackPtr tr;
- Boolean direction;
- {
- if (direction == LEFT) {
- if (TR.selStart > 0
- && is_at_word(tr, TR.selStart, TR.selEnd, LEFT)
- && _Track_is_white(tr, *(TR.hText), TR.selStart-1))
- return (TRUE);
- }
- else /* RIGHT */ {
- if (TR.selEnd < TR.textLength
- && is_at_word(tr, TR.selStart, TR.selEnd, RIGHT)
- && _Track_is_white(tr, *(TR.hText), TR.selEnd))
- return (TRUE);
- }
- return (FALSE);
- }
-
- /*
- * is_at_word(track_ptr, start, end, direction)
- * Use FindWord to decide whether start..end is a word at
- * the designated end. This routine is needed only if
- * you want "intelligent cut and paste."
- */
- static Boolean
- is_at_word(tr, start, end, direction)
- register TrackPtr tr;
- DOT start;
- DOT end;
- Boolean direction;
- {
- OffsetTable offsets;
-
- /*
- * This table has a bit set for characters that form
- * words. The bits are "numbered" from the left.
- * We need it to check on one-character selections
- * as they might be punctuation.
- */
- static long word_break[] = {
- 0x00000000, 0x0000FFC0, /* 00..3F (allow digits) */
- 0x7FFFFFE1, 0x7FFFFFE0, /* 40..7F (allow letters) */
- 0xFFFFFFFF, 0x01030003, /* 80..BF (int'l letters) */
- 0x001F0080, 0x00000000 /* C0..FF (a few more) */
- };
-
- if (TR.wordBreak != NIL) {
- if (direction == LEFT)
- return (_Track_is_white(tr, *TR.hText, start));
- else {
- return (_Track_is_white(tr, *TR.hText, end));
- }
- }
- if (!_Track_is_set(tr, _Track_use_script_manager)
- || !_Track_is_set(tr, _Track_use_smart_cut_paste))
- return (FALSE);
- if (direction == LEFT)
- FindWord(*TR.hText, end, start, TRUE, NIL, offsets);
- else {
- FindWord(*TR.hText, end, end, FALSE, NIL, offsets);
- }
- #if smgrVers >= 0x0210 /* See ScriptMgr.h */
- /*
- * In Think C version 4, the offset table is defined
- * as a 3-element structure.
- */
- #define START offsets[0].offFirst
- #define END offsets[0].offSecond
- #else
- /*
- * This is specific to Think C version 3, where the
- * offset table is defined as a 6-element short vector.
- * Warning: no longer tested.
- */
- #define START offsets[0]
- #define END offsets[1]
- #endif
- if ((END - START) == 1) {
- return (
- BitTst(word_break, (*TR.hText)[START])
- );
- }
- else {
- return ((END > START) ? TRUE : FALSE);
- }
- }
-